package com.chb.system.aspect;

import com.alibaba.fastjson.JSON;
import com.chb.system.annotation.OperLogAnnotation;
import com.chb.system.service.OperLogService;
import com.chb.system.service.UserService;
import com.chb.system.utils.IpUtils;
import com.hos.entity.sys.OperLog;
import com.hos.entity.sys.User;
import com.hos.utils.WebUtil;
import com.hos.vo.Result;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * @author ：张家琪
 * @date ：Created in 2023/12/26 9:34
 * @description：
 * @modified By：
 * @version:
 */
@Component
@Aspect
@Slf4j
public class OperLogAspect {


    @Autowired
    private HttpServletRequest request;
    @Autowired
    private OperLogService operLogService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Resource
    private UserService userService;

    @Pointcut("@annotation(com.chb.system.annotation.OperLogAnnotation)")
    private void pointcut() {
    }

    @Around("pointcut()")
    public Object my(ProceedingJoinPoint joinPoint) {
        // 添加日志--日志对象
        OperLog operLog = new OperLog();
        User user = getUserByToken();
        // 获取切面切入的方法对象
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        //      模块标题（前端展示效果为用户登录）
        operLog.setTitle("用户登录");
        //     业务类型（0其他 1新增 2修改 3删除 ）
        OperLogAnnotation annotation = method.getAnnotation(OperLogAnnotation.class);
        operLog.setBusinessType(annotation.business_type());
        //     方法名称
        operLog.setMethod(method.getName());
        //     请求方式
        operLog.setRequestMethod(request.getMethod());
        //     操作类别（0其他 1后台用户 2手机端用户）
        operLog.setOperatorType(annotation.operator_type());
        //     操作人员
        operLog.setOperName(user.getUserName());
        //     请求URL
        operLog.setOperUrl(request.getRequestURI());
        //     主机地址
        operLog.setOperIp(IpUtils.getIpAddress(request));
        // 设置ip地址
        Boolean outside = IpUtils.isOutside(request);
        if (!outside) {
            operLog.setOperLocation("内网IP");
        } else {
            operLog.setOperLocation("公网IP");
        }
        //     请求参数
        Object[] args = joinPoint.getArgs();
        operLog.setOperParam(JSON.toJSONString(args));
        //     操作时间
        operLog.setOperTime(new Date());
        try {
            Result result = (Result) joinPoint.proceed();
            if (result.getCode() == 200) {
                operLog.setJsonResult(result.toString());
            } else {
                //  错误信息
                operLog.setErrorMsg(result.toString());
            }
            return result;
        } catch (Throwable e) {
            log.error("日志Aop出现错误" + e.getMessage());
            throw new RuntimeException(e);
        } finally {
            this.operLogService.addOperLog(operLog);
        }
    }

    /**
     * @return com.hos.entity.sys.User
     * @create by: 陈海彬
     * @description: 获取请求用户的信息
     * @create time: 2023/12/12 10:39
     */
    private User getUserByToken() {
        String token = WebUtil.getToken();
        String phone = redisTemplate.opsForValue().get("user:" + token);
        return userService.findUserByPhone(phone);
    }
}